// access point to the API data
define(['jquery', 'eventbus'], function ($, eventbus) {
	// The base url of the API endpoint.
	let apiBaseUrl = "https://localhost:5001/api/";

	/**
	 * Sends a get request to the webservice.
	 *
	 * @param {string} url
	 * @param {function} callback
	 * @param {boolean} needsAuthorization
	 */
	let get = function (url, callback, needsAuthorization = false, suspendErrorMessage = false) {
		$.ajax({
			type: "GET",
			url: url,
			// Handle authorization before sending the request.
			beforeSend: function (xhr) {
				if (needsAuthorization) {
					let accessToken = localStorage.getItem("token");
					xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
				}
			},
			// On success execute the provided callback.
			success: function (data, status) {
				callback(data);
			},
			// On error display an error modal.
			error: function (jqXHR, textStatus, errorThrown) {
                if (!suspendErrorMessage) {
                    showAlert(jqXHR, textStatus, errorThrown);
                }
			}
		});
	}

	/**
	 * Sends a post request to the api endpoint.
	 *
	 * @param {string} url
	 * @param {function} callback
	 * @param {object} requestData
	 * @param {boolean} needsAuthorization
	 */
	let post = function (url, callback, requestData, needsAuthorization = false) {
		$.ajax({
			type: "POST",
			url: url,
			contentType: 'application/json',
			data: JSON.stringify(requestData),
			// Handle authorization before sending the request.
			beforeSend: function (xhr) {
				if (needsAuthorization) {
					let accessToken = localStorage.getItem("token");
					xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
				}
			},
			// On success execute the provided callback.
			success: function (data, status) {
				callback(data);
            },
			// On error display an error modal.
			error: function (jqXHR, textStatus, errorThrown) {
				showAlert(jqXHR, textStatus, errorThrown);
			}
		});
	}

	/**
	 * Notifies the components that an error was occured.
	 * 
	 * @param {object} jqXHR
	 * @param {string} textStatus
	 * @param {object} errorThrown
	 */
	let showAlert = function (jqXHR, textStatus, errorThrown) {
		let alertData = { title: "Error", text: "" };

		if (jqXHR.status === 401) alertData.text = "Wrong data provided in login process or this page requires you to log in.";
		else if (jqXHR.status === 400 || jqXHR.status === 500) alertData.text = "An error occured in the application. Try to reload the page and try again.";
		else alertData.text = "Unknown error has occured in the application. Try to reload the page and try again."

		eventbus.publish("showAlertEvent", alertData);
	}

	let getSearchHistory = function (callback, url = apiBaseUrl + "searches") {
		get(url, callback, true);
	}

	let getSearches = function (callback, url = apiBaseUrl + "searches/search") {
		get(url, callback, true);
	}

	let getQuestions = function (callback, url = apiBaseUrl + "questions") {
		get(url, callback, false);
	}

	let getQuestionDetails = function (callback, url) {
		get(url, callback, true);
	}

	let getAccountDetails = function (callback, suspendErrorMessage) {
		get(apiBaseUrl + "accounts", callback, true, suspendErrorMessage);
	}

	let getMarkedQuestions = function (callback) {
		get(apiBaseUrl + "marked_questions", callback, true);
	}

	let postLoginAttempt = function (callback, loginData) {
		post(apiBaseUrl + "accounts/login", callback, loginData);
	}

	let postNewAccount = function (callback, registrationData) {
		post(apiBaseUrl + "accounts", callback, registrationData);
	}

	let getWeightedWords = function (callback, userInput) {
		get(apiBaseUrl + "weighted_words/" + userInput, callback, true);
	}

	let postMarkedQuestion = function (callback, markQuestionData) {
		post(apiBaseUrl + "marked_questions", callback, markQuestionData, true);
	}


	return {
		getSearchHistory,
		getSearches,
		getQuestions,
		getQuestionDetails,
		getAccountDetails,
		getMarkedQuestions,
		postLoginAttempt,
		postNewAccount,
		getWeightedWords,
		postMarkedQuestion,
	};
});
